

import { errLog } from "../../../util/log";
import { getRoomDomain } from "../../../global/map";
import { GroupExplorers } from "../functional/explorers";
import { GroupCluster } from "./cluster";

export class ClusterExplorers extends GroupCluster{
    constructor(spawnRoom = undefined){
        super(spawnRoom)
        if(spawnRoom !== undefined){
            this.explorerGroups = {};
        }
    }
    serialize(){
        let explorerGroups = {};
        for(let roomName in this.explorerGroups){
            let explorerGroup = this.explorerGroups[roomName];
            explorerGroups[roomName] = explorerGroup.serialize();
        }
        return {
            super: super.serialize(),
            explorerGroups: explorerGroups,
        }
    }
    deserialize(obj){
        super.deserialize(obj.super);

        this.explorerGroups = {};
        for(let roomName in obj.explorerGroups){
            let explorerGroupObj = obj.explorerGroups[roomName];
            this.explorerGroups[roomName] = new GroupExplorers().deserialize(explorerGroupObj);
        }
        return this;
    }
    get size(){
        let ans = 0;
        for(let roomName in this.explorerGroups){
            if(Boolean(Game.rooms[roomName])){
                ans++;
                continue;
            }
            let group = this.explorerGroups[roomName];
            if(group instanceof GroupExplorers){
                ans++;
                // ans+=group.size;
            }
        }
        return ans;
    }
    get maxSize(){
        return getRoomDomain(this.spawnRoom).length;
        // let ans = 0;
        // for(let roomName of getRoomDomain(this.spawnRoom)){
        //     if(Boolean(Game.rooms[roomName])){
        //         continue;
        //     }
        //     ans++;
        // }
        // return ans;
    }
    spawn(){
        if(this.size>=this.maxSize){
            errLog(new Error("too many explorers"))
            return ERR_FULL;
        }
        let roomDomain = getRoomDomain(this.spawnRoom);
        let ret=ERR_INVALID_ARGS;
        for(let roomName of roomDomain){
            if(Boolean(Game.rooms[roomName])){
                continue;
            }
            try{
                let explorerGroup = this.explorerGroups[roomName];
                let ret0;
                if(explorerGroup instanceof GroupExplorers){
                    if(explorerGroup.size<explorerGroup.maxSize){
                        ret0 = explorerGroup.spawn();
                    }
                }else{
                    ret0 =  this.sendExplorer(roomName);
                }
                if(ret0 === OK){
                    ret = OK;
                }else if(ret0 === ERR_BUSY){
                    break;
                }
            }catch(e){
                errLog(e);
            }
        }
        return ret;
    }
    run(){
        for(let roomName in this.explorerGroups){
            let explorerGroup = this.explorerGroups[roomName];
            try{
                explorerGroup.run();
            }catch(e){
                errLog(e);
            }
        }
    }

    /**
     * 
     * @param {RoomPosition | String} targetRoom 
     */
    sendExplorer(targetRoom){
        if(targetRoom===undefined){
            throw new Error('target undefined');
        }

        let targetPos;
        let targetRoomName;
        if(targetRoom instanceof RoomPosition){
            targetPos=targetRoom;
            targetRoomName=targetRoom.roomName;
        }else if(typeof targetRoom==='string'){
            targetRoomName=targetRoom;
            targetPos=new RoomPosition(24,24,targetRoomName);
        }else{
            throw new Error('unknown target type');
        }

        if(Game.rooms[targetRoomName]!=undefined){
            return ERR_INVALID_TARGET;
        }
        
        this.explorerGroups[targetRoomName] = new GroupExplorers(this.spawnRoom, targetPos);

        return OK;
    }
}